package com.kexilo.core.common.aspect;

import com.kexilo.core.common.annotation.RateLimiter;
import com.kexilo.core.common.exception.ServiceException;
import com.kexilo.core.common.utils.IpUtils;
import com.kexilo.core.common.utils.RedisUtils;
import com.kexilo.core.common.utils.SecurityUtils;
import com.kexilo.core.common.utils.ServletUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 限流处理切面
 * 
 * @author Kexilo
 */
@Aspect
@Component
public class RateLimiterAspect {
    
    private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class);
    
    @Autowired
    private RedisUtils redisUtils;
    
    @Before("@annotation(rateLimiter)")
    public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable {
        String key = getCombineKey(rateLimiter, point);
        
        // 检查限流
        boolean allowed = redisUtils.rateLimit(key, rateLimiter.count(), rateLimiter.time());
        
        if (!allowed) {
            log.warn("限流触发: key={}, count={}, time={}", key, rateLimiter.count(), rateLimiter.time());
            throw new ServiceException(rateLimiter.message());
        }
        
        log.debug("限流检查通过: key={}", key);
    }
    
    /**
     * 获取限流key
     */
    public String getCombineKey(RateLimiter rateLimiter, JoinPoint point) {
        StringBuilder stringBuffer = new StringBuilder(rateLimiter.key());
        
        if (rateLimiter.limitType() == RateLimiter.LimitType.IP) {
            // IP限流
            stringBuffer.append(IpUtils.getIpAddr(ServletUtils.getRequest())).append("-");
        } else if (rateLimiter.limitType() == RateLimiter.LimitType.USER) {
            // 用户限流
            try {
                String username = SecurityUtils.getUsername();
                stringBuffer.append(username).append("-");
            } catch (Exception e) {
                // 如果获取不到用户信息，使用IP
                stringBuffer.append(IpUtils.getIpAddr(ServletUtils.getRequest())).append("-");
            }
        }
        
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        Class<?> targetClass = method.getDeclaringClass();
        stringBuffer.append(targetClass.getName()).append("-").append(method.getName());
        
        return stringBuffer.toString();
    }
}
